﻿#include "model.h"
#include "m_combinatorics.h"
//#include "fenv.h"


m_combinatorics::m_combinatorics()
{
    m=0;
    n=0;
    name = QObject::tr("Комбинаторика");
}

m_combinatorics::m_combinatorics(int _m, int _n)
{
    setMN(_m, _n);
}

double m_combinatorics::C()
{
    double result=1;
    int i=1;
    int j=n;
    int max,min;
    if ( m > (n-m) )//ищем, на что будем сокращать верхний факториал
    {
        max = m;
        min = (n-m);
    }
    else
    {
        max = (n-m);
        min = m;
    }
    while(i<=min || j>max)
    {
        if(j>max)
        {
            result*=j;
            /*if( fetestexcept (FE_OVERFLOW) )
                return -1;*/
        }
        if(i<=min)
        {
            result/=i;
            /*if( fetestexcept (FE_UNDERFLOW) )
                return -2;*/
        }
        ++i;
        --j;
    }
    return result;
}

double m_combinatorics::A()
{
    double result=1;
    int j=n;
    while(j>(n-m))
    {
        result*=j;
        /*if( fetestexcept (FE_OVERFLOW) )
            return -1;*/
        --j;
    }
    return result;
}

double m_combinatorics::P()
{
    return fact(n);
}

double m_combinatorics::Ct()
{
    int old_n=n;
    n=n+m-1;
    double r = C();
    n=old_n;
    return r;
}

double m_combinatorics::At()
{
    double r = 1;
    for (int i=0; i<m; ++i)
    {
        r*=n;
    }
    return r;
}

double m_combinatorics::Pt(QVector<int> v)
{
    double result=1;
    int i,j;
    int count = v.count();
    if(count == 0)
        return 0;//есть ли элементы
    int max=v[0];//поиск маскимума
    int max_index=0;
    for(i=0;i<count;++i)
    {
        if(v[i] > max)
        {
            max = v[i];
            max_index = i;
        }
    }
    v.remove(max_index);//удаляем максимум
    i=1;
    j=n;
    while(i<=n)//модный цикл считает результат
    {
        if(j>max)
        {
            result*=j;
            /*if( fetestexcept (FE_OVERFLOW) )
                return -1;*/
        }
        for(int k=0;k<v.count();++k)
        {
            if(i<=v[k])
            {
                result/=i;
                /*if( fetestexcept (FE_UNDERFLOW) )
                    return -2;*/
            }
        }
        ++i;
        --j;
    }
    return result;
}

m_combinatorics & m_combinatorics::setMN(int _m, int _n)
{
    if(_m<0)
        m = 0;
    else
        m=_m;
    if(_n<0 )
        n = 0;
    else
        n=_n;

    return *this;
}
